/*
* $Id$
*
* SARL is an general-purpose agent programming language.
* More details on http://www.sarl.io
*
* Copyright (C) 2014-2017 the original authors or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.sarl.tests.api;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.Logger;
import com.google.common.base.Joiner;
import com.google.common.base.Objects;
import com.google.common.base.Predicate;
import com.google.common.base.Strings;
import com.google.common.collect.Collections2;
import com.google.common.collect.Iterables;
import com.google.inject.Inject;
import com.google.inject.Injector;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.xtend.core.macro.ProcessorInstanceForJvmTypeProvider;
import org.eclipse.xtend.core.xtend.XtendParameter;
import org.eclipse.xtend.core.xtend.XtendTypeDeclaration;
import org.eclipse.xtext.common.types.JvmConstructor;
import org.eclipse.xtext.common.types.JvmOperation;
import org.eclipse.xtext.common.types.JvmTypeReference;
import org.eclipse.xtext.diagnostics.Severity;
import org.eclipse.xtext.resource.XtextResourceSet;
import org.eclipse.xtext.testing.InjectWith;
import org.eclipse.xtext.testing.XtextRunner;
import org.eclipse.xtext.testing.util.ParseHelper;
import org.eclipse.xtext.testing.validation.ValidationTestHelper;
import org.eclipse.xtext.util.JavaVersion;
import org.eclipse.xtext.util.ReflectionUtil;
import org.eclipse.xtext.validation.Issue;
import org.eclipse.xtext.xbase.XExpression;
import org.eclipse.xtext.xbase.XNullLiteral;
import org.eclipse.xtext.xbase.XNumberLiteral;
import org.eclipse.xtext.xbase.XStringLiteral;
import org.eclipse.xtext.xbase.lib.IterableExtensions;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.AssumptionViolatedException;
import org.junit.ComparisonFailure;
import org.junit.Rule;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
import org.junit.runner.RunWith;
import org.junit.runners.model.Statement;
import org.mockito.ArgumentMatcher;
import org.mockito.ArgumentMatchers;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.internal.matchers.InstanceOf;
import org.mockito.internal.matchers.Null;
import org.mockito.internal.matchers.Or;
import org.mockito.internal.util.Primitives;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Version;
import io.sarl.lang.SARLVersion;
import io.sarl.lang.jvmmodel.SarlJvmModelAssociations;
import io.sarl.lang.sarl.SarlAction;
import io.sarl.lang.sarl.SarlAgent;
import io.sarl.lang.sarl.SarlAnnotationType;
import io.sarl.lang.sarl.SarlBehavior;
import io.sarl.lang.sarl.SarlBehaviorUnit;
import io.sarl.lang.sarl.SarlCapacity;
import io.sarl.lang.sarl.SarlClass;
import io.sarl.lang.sarl.SarlConstructor;
import io.sarl.lang.sarl.SarlEnumeration;
import io.sarl.lang.sarl.SarlEvent;
import io.sarl.lang.sarl.SarlField;
import io.sarl.lang.sarl.SarlFormalParameter;
import io.sarl.lang.sarl.SarlInterface;
import io.sarl.lang.sarl.SarlScript;
import io.sarl.lang.sarl.SarlSkill;
/** Abstract class that is providing useful tools for unit tests.
*
* This class provides assertion functions, clear any property
* related to Sarl, and reset the attributes of the unit test that
* are marked <code>@Mock</code>, <code>@InjectMocks</code> or
* <code>@Nullable</code>.
*
* @param <S> - the type of the service.
* @author $Author: sgalland$
* @version $FullVersion$
* @mavengroupid $GroupId$
* @mavenartifactid $ArtifactId$
*/
@SuppressWarnings("all")
@RunWith(XtextRunner.class)
@InjectWith(ExtendedSARLInjectorProvider.class)
public abstract class AbstractSarlTest {
/** URL of the Maven central repository.
*/
public static final String MAVEN_CENTRAL_REPOSITORY_URL = "http://repo1.maven.org/maven2/io/sarl/lang/io.sarl.lang.core/0.2.0/io.sarl.lang.core-0.2.0.pom";
/** Timeout for connecting to the Maven central server (in milliseconds).
*/
public static final int MAVEN_CENTRAL_TIMEOUT = 15000;
/** Precision of the floating point number epsilon-tests.
*/
public static final int DEFAULT_DECIMAL_COUNT = 6;
@Inject
private ValidationTestHelper validationHelper;
@Inject
private Injector injector;
@Inject
private ParseHelper<SarlScript> parser;
@Inject
private SarlJvmModelAssociations associations;
/** Utility for reflection.
*/
@Inject
public ReflectExtensions reflect;
/** Temporary fixing a bug in the class loading of Mockito 2.
*
* @param type the type to mock.
* @return the mocked instance.
* @see http://stackoverflow.com/questions/37702952/classnotfoundexception-with-mockito-2-in-osgi
*/
public static <T> T mock(Class<T> type) {
if (type == null) {
return null;
}
final ClassLoader loader = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(Mockito.class.getClassLoader());
try {
return Mockito.mock(type);
} finally {
Thread.currentThread().setContextClassLoader(loader);
}
}
/** Temporary fixing a bug in the class loading of Mockito 2.
*
* @param instance the instance to spy.
* @return the spied instance.
* @see http://stackoverflow.com/questions/37702952/classnotfoundexception-with-mockito-2-in-osgi
*/
public static <T> T spy(T instance) {
if (instance == null) {
return null;
}
final ClassLoader loader = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(Mockito.class.getClassLoader());
try {
return Mockito.spy(instance);
} finally {
Thread.currentThread().setContextClassLoader(loader);
}
}
/** Replies if the runtime environment is Eclipse.
*
* @return <code>true</code> if the runtime environment is Eclipse.
*/
protected static boolean isEclipseRuntimeEnvironment() {
final String cmd = System.getProperty("sun.java.command", "");
// Assuming that the Maven launcher is providing an absolute path to the launcher.
return cmd != null
&& (cmd.startsWith("org.eclipse.equinox.launcher.Main")
|| cmd.startsWith("org.eclipse.jdt.internal.junit."));
}
/** This rule permits to clean automatically the fields
* at the end of the test.
*/
@Rule
public TestWatcher rootSarlWatchter = new TestWatcher() {
private boolean isMockable() {
boolean isMockable = false;
Class<?> type = AbstractSarlTest.this.getClass();
while (type != null && !AbstractSarlTest.class.equals(type)) {
if (type.getAnnotation(ManualMocking.class) != null) {
return false;
}
for (Field field : type.getDeclaredFields()) {
if (field.getAnnotation(Mock.class) != null
|| field.getAnnotation(InjectMocks.class) != null) {
isMockable = true;
}
}
type = type.getSuperclass();
}
return isMockable;
}
@Override
protected void starting(Description description) {
// Check if the minimal version of Java is used for running the tests.
final JavaVersion cVersion = JavaVersion.fromQualifier(System.getProperty("java.specification.version"));
final JavaVersion mVersion = JavaVersion.fromQualifier(SARLVersion.MINIMAL_JDK_VERSION);
if (!cVersion.isAtLeast(mVersion)) {
throw new Error("You must use JDK " + SARLVersion.MINIMAL_JDK_VERSION + " for running the tests.");
}
//
if (isMockable()) {
MockitoAnnotations.initMocks(AbstractSarlTest.this);
}
}
@Override
public Statement apply(Statement base, Description description) {
// This test is working only in Eclipse, or Maven/Tycho.
TestScope scope = description.getAnnotation(TestScope.class);
if (scope == null) {
Class<?> enclosingType = description.getTestClass();
while (scope == null && enclosingType != null) {
scope = enclosingType.getAnnotation(TestScope.class);
enclosingType = enclosingType.getEnclosingClass();
}
}
if (scope != null) {
if (!scope.tycho() && !scope.eclipse()) {
throw new AssumptionViolatedException("not running on the current framework");
} else if (scope.tycho() || scope.eclipse()) {
boolean isEclipse = isEclipseRuntimeEnvironment();
if (scope.tycho()) {
Assume.assumeFalse(isEclipse);
} else {
Assume.assumeTrue(isEclipse);
}
}
if (scope.needmavencentral()) {
boolean canAccessNetwork = true;
try {
URL central = new URL(MAVEN_CENTRAL_REPOSITORY_URL);
URLConnection connection = central.openConnection();
connection.setConnectTimeout(MAVEN_CENTRAL_TIMEOUT);
try (InputStream is = connection.getInputStream()) {
byte[] buffer = new byte[128];
int length = is.read(buffer);
while (length > 0) {
length = is.read(buffer);
}
}
} catch (Exception exception) {
canAccessNetwork = false;
}
Assume.assumeTrue(canAccessNetwork);
}
}
//
return super.apply(base, description);
}
private boolean isNullable(Field field) {
if (field.getAnnotation(Mock.class) != null
|| field.getAnnotation(InjectMocks.class) != null) {
return true;
}
for (Annotation annotation : field.getAnnotations()) {
if ("Nullable".equals(annotation.annotationType().getSimpleName())
|| "NonNullByDefault".equals(annotation.annotationType().getSimpleName())) {
return true;
}
}
return true;
}
@Override
protected void finished(Description description) {
// Clear the references to the mock objects or the injected objects
Class<?> type = AbstractSarlTest.this.getClass();
while (type != null && !Object.class.equals(type)) {
for (Field field : type.getDeclaredFields()) {
if (isNullable(field) && (field.getModifiers() & (Modifier.FINAL | Modifier.STATIC)) == 0) {
boolean isAcc = field.isAccessible();
try {
field.setAccessible(true);
field.set(AbstractSarlTest.this, null);
} catch (Exception e) {
throw new Error(e);
} finally {
field.setAccessible(isAcc);
}
}
}
type = type.getSuperclass();
}
}
};
/** Helpfer for setting a field, even if it is not visible.
*
* @param instance - the object.
* @param fieldType - the type of the field.
* @param fieldName - the name of the field.
* @param fieldValue - the field value.
*/
public static <T> void setField(Object instance, Class<T> fieldType,
String fieldName, T fieldValue) {
Field field = null;
Class<?> type = instance.getClass();
while (type != null) {
try {
field = type.getDeclaredField(fieldName);
assertEquals(fieldType, field.getType());
boolean acc = field.isAccessible();
try {
field.setAccessible(true);
field.set(instance, fieldValue);
return;
} finally {
field.setAccessible(acc);
}
} catch (Throwable exception) {
type = type.getSuperclass();
}
}
throw new NoSuchFieldError(fieldName);
}
/** Assert the values are equal.
*
* @param expected the expected value.
* @param actual the actual value.
* @param epsilon the precision.
*/
public static void assertEquals(float expected, float actual, float precision) {
Assert.assertEquals(expected, actual, precision);
}
/** Assert the values are equal.
*
* @param expected the expected value.
* @param actual the actual value.
* @param epsilon the precision.
*/
public static void assertEquals(double expected, double actual, double precision) {
Assert.assertEquals(expected, actual, precision);
}
/** Assert the values are equal.
*
* @param expected the expected value.
* @param actual the actual value.
* @param epsilon the precision.
*/
public static void assertEpsilonEquals(double expected, double actual) {
if (!isEpsilonEquals(expected, actual, true)) {
throw new ComparisonFailure("Values are not equal.", Double.toString(expected), Double.toString(actual));
}
}
/** Replies if two values are equals at espilon.
*
* @param v1 the first value.
* @param v2 the second value.
* @param isNaNEqual indicates if the NaN value is equals to itself.
* @return <code>true</code> or <code>false</code>
*/
public static boolean isEpsilonEquals(double v1, double v2, boolean isNaNEqual) {
if (v1 == v2) {
return true;
}
final boolean nanA = Double.isNaN(v1);
final boolean nanB = Double.isNaN(v2);
if (nanA || nanB) {
if (isNaNEqual) {
return nanA == nanB;
}
return false;
}
if (!Double.isInfinite(v1) && !Double.isInfinite(v1)
&& !Double.isNaN(v1) && !Double.isNaN(v2)) {
return isEpsilonEquals(new BigDecimal(v1), new BigDecimal(v2), DEFAULT_DECIMAL_COUNT / 2);
}
return false;
}
/** Replies if two values are equals at espilon.
*
* @param v1 the first value.
* @param v2 the second value.
* @param precision is the number of decimal digits to test.
* @return <code>true</code> or <code>false</code>
*/
public static boolean isEpsilonEquals(BigDecimal v1, BigDecimal v2, int precision) {
final BigDecimal ma = v1.movePointRight(precision);
final BigDecimal mb = v2.movePointRight(precision);
BigDecimal aa = ma.setScale(0, BigDecimal.ROUND_HALF_UP);
BigDecimal bb = mb.setScale(0, BigDecimal.ROUND_HALF_UP);
if (aa.compareTo(bb) == 0) {
return true;
}
aa = ma.setScale(0, BigDecimal.ROUND_DOWN);
bb = mb.setScale(0, BigDecimal.ROUND_DOWN);
return aa.compareTo(bb) == 0;
}
/**
* Test if the given exception has a cause of the given type.
*
* If the given exception has no cause, it is the cause.
*
* @param <T> - the type of the expected cause.
* @param expected - the type of the expected cause.
* @param actual - the exception to test.
* @return the cause.
*/
public static <T extends Throwable> T assertCause(Class<T> expected, Throwable actual) {
Throwable cause = actual;
while (cause != null && cause.getCause() != null && cause.getCause() != cause) {
cause = cause.getCause();
}
if (cause == null) {
cause = actual;
}
assertTrue("Unexpected type of exception's cause. Expected: " + expected.getName() + ". Actual: "
+ cause.getClass().getName(), expected.isInstance(cause));
return expected.cast(cause);
}
/** Test if the objects are equal.
*
* @param message - the message.
* @param actual - the collection to test.
* @param expected - the expected objects.
*/
public static void assertEquals(String message, Object expected, Object actual) {
if (!Objects.equal(expected, actual)) {
String s1 = java.util.Objects.toString(expected);
String s2 = java.util.Objects.toString(actual);
throw new ComparisonFailure(message, s1, s2);
}
}
/** Test if the objects are equal.
*
* @param message - the message.
* @param actual - the collection to test.
* @param expected - the expected objects.
*/
public static void assertEquals(Object expected, Object actual) {
assertEquals(null, expected, actual);
}
/** Check if the given value is <code>null</code> or empty.
*
* @param actual
*/
public static void assertNullOrEmpty(Iterable<?> actual) {
if (actual != null) {
assertFalse("Not null nor empty", actual.iterator().hasNext());
}
}
/** Check if the given value is <code>null</code> or empty.
*
* @param actual
*/
public static void assertNullOrEmpty(String actual) {
if (!Strings.isNullOrEmpty(actual)) {
fail("Not null nor empty. Actual value: " + actual);
}
}
/** Check if the given value is not <code>null</code> nor empty.
*
* @param actual
*/
public static void assertNotNullOrEmpty(String actual) {
if (Strings.isNullOrEmpty(actual)) {
fail("Null or empty.");
}
}
/** Test if the actual collection/iterable contains all the expected objects.
*
* @param actual - the collection to test.
* @param expected - the expected objects.
*/
public static void assertContains(Iterable<?> actual, Object... expected) {
assertContainsCollection(actual, Arrays.asList(expected));
}
/** Test if the actual collection/iterable contains all the expected objects.
*
* @param actual - the collection to test.
* @param expected - the expected objects.
*/
public static void assertContainsCollection(Iterable<?> actual, Iterable<?> expected) {
assertNotNull(actual);
Collection<Object> la = new ArrayList<>();
Iterables.addAll(la, actual);
Collection<Object> le = new ArrayList<>();
Iterables.addAll(le, expected);
final SortedSet<String> unexpectedElements = new TreeSet<>();
Iterator<?> it1 = la.iterator();
while (it1.hasNext()) {
Object ac = it1.next();
it1.remove();
if (ac != null && !le.remove(ac)) {
unexpectedElements.add(ac.toString());
}
}
if (!unexpectedElements.isEmpty()) {
fail("Unexpected elements:\n" + unexpectedElements.toString() + "\nActual elements are:\n" +
Iterables.toString(actual));
} else if (!le.isEmpty()) {
fail("Expecting the following elements:\n" + le.toString() + "\nbut was:\n" +
Iterables.toString(actual));
}
}
/** Test if the actual collection/iterable contains at least all the expected objects.
*
* @param actual - the collection to test.
* @param expected - the expected objects.
*/
public static void assertPartlyContains(Iterable<?> actual, Object... expected) {
assertPartlyContainsCollection(actual, Arrays.asList(expected));
}
/** Test if the actual collection/iterable contains at least all the expected objects.
*
* @param actual - the collection to test.
* @param expected - the expected objects.
*/
public static void assertPartlyContainsCollection(Iterable<?> actual, Iterable<?> expected) {
assertNotNull(actual);
Collection<Object> la = new ArrayList<>();
Iterables.addAll(la, actual);
Collection<Object> le = new ArrayList<>();
Iterables.addAll(le, expected);
Iterator<?> it1 = la.iterator();
while (it1.hasNext()) {
Object ac = it1.next();
it1.remove();
le.remove(ac);
}
if (!le.isEmpty()) {
fail("Expecting the following elements:\n" + le.toString() + "\nbut was:\n" +
Iterables.toString(actual));
}
}
/** Test if the actual collection/iterable contains all the expected objects.
*
* @param actual - the collection to test.
* @param expected - the expected objects.
*/
public static void assertContainsStrings(Iterable<?> actual, String... expected) {
assertContainsStringCollection(actual, Arrays.asList(expected));
}
/** Test if the actual collection/iterable contains all the expected objects.
*
* @param actual - the collection to test.
* @param expected - the expected objects.
*/
public static void assertContainsStringCollection(Iterable<?> actual, Iterable<String> expected) {
assertNotNull(actual);
Collection<Object> la = new ArrayList<>();
Iterables.addAll(la, actual);
Collection<String> le = new ArrayList<>();
Iterables.addAll(le, expected);
Iterator<?> it1 = la.iterator();
while (it1.hasNext()) {
Object ac = it1.next();
it1.remove();
if (!le.remove(ac.toString())) {
fail("Unexpecting element: " + ac);
return;
}
}
if (!le.isEmpty()) {
fail("Expecting the following elements:\n" + le.toString() + "\nbut was:\n" +
Iterables.toString(actual));
}
}
/** Assert if the value is the string representation of
* the boolean vlaue <code>true</code>.
*
* @param actual - the value.
*/
public static void assertTrueStr(String actual) {
assertTrueStr(null, actual);
}
/** Assert if the value is the string representation of
* the boolean vlaue <code>true</code>.
*
* @param message - the error message.
* @param actual - the value.
*/
public static void assertTrueStr(String message, String actual) {
assertEquals(message, Boolean.TRUE.toString(), actual);
}
/** Assert if the value is the string representation of
* the boolean vlaue <code>false</code>.
*
* @param actual - the value.
*/
public static void assertFalseStr(String actual) {
assertFalseStr(null, actual);
}
/** Assert if the value is the string representation of
* the boolean vlaue <code>false</code>.
*
* @param message - the error message.
* @param actual - the value.
*/
public static void assertFalseStr(String message, String actual) {
assertEquals(message, Boolean.FALSE.toString(), actual);
}
/** Assert if the system property with the given name has
* the boolean value <code>true</code>.
*
* The property must be defined
*
* @param name - the name of the property.
*/
public static void assertTrueProperty(String name) {
String v = System.getProperty(name);
if (Strings.isNullOrEmpty(v)) {
fail("The property '" + name + "' is not defined.");
}
assertTrueStr("The property '" + name + "' is expected to be true.", v);
}
/** Assert if the system property with the given name has
* the boolean value <code>false</code>.
*
* @param name - the name of the property.
*/
public static void assertFalseProperty(String name) {
String v = System.getProperty(name);
if (Strings.isNullOrEmpty(v)) {
fail("The property '" + name + "' is not defined.");
}
assertFalseStr("The property '" + name + "' is expected to be true.", v);
}
/** Assert if the system property with the given name has
* the boolean value <code>false</code>.
*
* @param name - the name of the property.
*/
public static void assertNullProperty(String name) {
String v = System.getProperty(name);
if (!Strings.isNullOrEmpty(v)) {
fail("The property '" + name + "' is expected to be undefined; but is has the value: " + v);
}
}
/** Assert if the system property with the given name has
* the given value.
*
* @param name - the name of the property.
* @param value - the value of the property.
*/
public static void assertProperty(String name, String value) {
if (Strings.isNullOrEmpty(value)) {
assertNullProperty(name);
} else {
String v = System.getProperty(name);
if (Strings.isNullOrEmpty(v)) {
fail("The property '" + name + "' is expected to be defined." + v);
}
assertEquals(value, v);
}
}
/** Assert that the given value is stricty positive.
*
* @param actual - the value to test.
*/
public static void assertStrictlyPositive(int actual) {
if (actual <= 0) {
fail("Expecting a strictly positive number, actual: " + actual); //$NON-NLS-1$
}
}
/** Assert that the given value is stricty negative.
*
* @param actual - the value to test.
*/
public static void assertStrictlyNegative(int actual) {
if (actual >= 0) {
fail("Expecting a strictly negative number, actual: " + actual); //$NON-NLS-1$
}
}
/** Assert that the given value is stricty positive.
*
* @param actual - the value to test.
*/
public static void assertPositiveOrZero(int actual) {
if (actual < 0) {
fail("Expecting a positive or zero number, actual: " + actual); //$NON-NLS-1$
}
}
/** Assert that the given value is negative or zero.
*
* @param actual - the value to test.
*/
public static void assertNegativeOrZero(int actual) {
if (actual > 0) {
fail("Expecting a negative or zero number, actual: " + actual); //$NON-NLS-1$
}
}
/** Assert that the given value is stricty positive.
*
* @param actual - the value to test.
*/
public static void assertStrictlyPositive(float actual) {
if (actual <= 0f) {
fail("Expecting a strictly positive number, actual: " + actual); //$NON-NLS-1$
}
}
/** Assert that the given value is stricty negative.
*
* @param actual - the value to test.
*/
public static void assertStrictlyNegative(float actual) {
if (actual >= 0f) {
fail("Expecting a strictly negative number, actual: " + actual); //$NON-NLS-1$
}
}
/** Assert that the given value is stricty positive.
*
* @param actual - the value to test.
*/
public static void assertPositiveOrZero(float actual) {
if (actual < 0f) {
fail("Expecting a positive or zero number, actual: " + actual); //$NON-NLS-1$
}
}
/** Assert that the given value is negative or zero.
*
* @param actual - the value to test.
*/
public static void assertNegativeOrZero(float actual) {
if (actual > 0f) {
fail("Expecting a negative or zero number, actual: " + actual); //$NON-NLS-1$
}
}
/** Assert that the given value is stricty positive.
*
* @param actual - the value to test.
*/
public static void assertStrictlyPositive(double actual) {
if (actual <= 0.) {
fail("Expecting a strictly positive number, actual: " + actual); //$NON-NLS-1$
}
}
/** Assert that the given value is stricty negative.
*
* @param actual - the value to test.
*/
public static void assertStrictlyNegative(double actual) {
if (actual >= 0.) {
fail("Expecting a strictly negative number, actual: " + actual); //$NON-NLS-1$
}
}
/** Assert that the given value is stricty positive.
*
* @param actual - the value to test.
*/
public static void assertPositiveOrZero(double actual) {
if (actual < 0.) {
fail("Expecting a positive or zero number, actual: " + actual); //$NON-NLS-1$
}
}
/** Assert that the given value is negative or zero.
*
* @param actual - the value to test.
*/
public static void assertNegativeOrZero(double actual) {
if (actual > 0.) {
fail("Expecting a negative or zero number, actual: " + actual); //$NON-NLS-1$
}
}
/** Assert that the given value is equal to zero.
*
* @param actual - the value to test.
*/
public static void assertZero(int actual) {
assertZero(null, actual);
}
/** Assert that the given value is equal to zero.
*
* @param message - the error message.
* @param actual - the value to test.
*/
public static void assertZero(String message, int actual) {
if (actual != 0) {
String msg;
if (!Strings.isNullOrEmpty(message)) {
msg = message + ". "; //$NON-NLS-1$
} else {
msg = ""; //$NON-NLS-1$
}
fail(msg + "Expecting a zero number, actual: " + actual); //$NON-NLS-1$
}
}
/** Assert that the given value is NaN.
*
* @param actual - the value to test.
*/
public static void assertNaN(float actual) {
assertNaN(null, actual);
}
/** Assert that the given value is NaN.
*
* @param message - the error message.
* @param actual - the value to test.
*/
public static void assertNaN(String message, float actual) {
if (!Float.isNaN(actual)) {
String msg;
if (!Strings.isNullOrEmpty(message)) {
msg = message + ". "; //$NON-NLS-1$
} else {
msg = ""; //$NON-NLS-1$
}
fail(msg + "Expecting NaN, actual: " + actual); //$NON-NLS-1$
}
}
/** Assert that the given value is NaN.
*
* @param actual - the value to test.
*/
public static void assertNaN(double actual) {
assertNaN(null, actual);
}
/** Assert that the given value is NaN.
*
* @param message - the error message.
* @param actual - the value to test.
*/
public static void assertNaN(String message, double actual) {
if (!Double.isNaN(actual)) {
String msg;
if (!Strings.isNullOrEmpty(message)) {
msg = message + ". "; //$NON-NLS-1$
} else {
msg = ""; //$NON-NLS-1$
}
fail(msg + "Expecting NaN, actual: " + actual); //$NON-NLS-1$
}
}
/** Assert that the two given arrays contain the same values even
* they are not in the same order.
*
* @param expected - the expected values.
* @param actual - the actual values.
*/
public static <T> void assertArraySimilar(T[] expected, T[] actual) {
List<T> expectedValues = new ArrayList<>(Arrays.asList(expected));
List<T> actualValues = new ArrayList<>(Arrays.asList(actual));
Iterator<T> iterator = expectedValues.iterator();
while (iterator.hasNext()) {
T v = iterator.next();
iterator.remove();
if (!actualValues.remove(v)) {
fail("Expecting a value in the array: " + v); //$NON-NLS-1$
}
}
if (!expectedValues.isEmpty()) {
fail("Expecting a value(s) in the array: " + expectedValues); //$NON-NLS-1$
}
}
/** Assert that the given value is inside the array..
*
* @param expected - the array.
* @param actual - the value.
*/
public static <T> void assertArrayContains(T[] expected, T actual) {
for (T value : expected) {
if (Objects.equal(actual, value)) {
return;
}
}
fail("Unable to find the value in the array, value: " + actual //$NON-NLS-1$
+ "\narray: " + Arrays.toString(expected)); //$NON-NLS-1$
}
/** Replies the OS-dependent line separator.
*
* @return the line separator from the {@code "line.separator"} property, or {@code "\n"}.
* @since 0.5
*/
public static String getLineSeparator() {
final String nl = System.getProperty("line.separator");
if (Strings.isNullOrEmpty(nl)) {
return "\n";
}
return nl;
}
/** Helper for writting a multiline string in unit tests, which supports the
* OS-dependent line separator.
*
* @param lines - the lines in the string.
* @return the complete multiline string.
*/
public static String multilineString(Object... lines) {
return Joiner.on(getLineSeparator()).join(lines);
}
/** Assert that the given iterable object replies the expected identifiers.
*
* The order of the identifier is significant.
*
* @param actualReferences - the actual elements.
* @param expectedIdentifiers - the expected elements.
* @see JvmTypeReference#getIdentifier()
*/
public static void assertTypeReferenceIdentifiers(Iterable<? extends JvmTypeReference> actualReferences, String... expectedIdentifiers) {
int i = 0;
for (JvmTypeReference reference : actualReferences) {
assertTypeReferenceIdentifier(reference, expectedIdentifiers[i]);
++i;
}
if (i < expectedIdentifiers.length) {
fail("Not enough identifiers. Expected: " + Arrays.toString(expectedIdentifiers)
+ "Actual: " + Iterables.toString(actualReferences));
}
}
/** Assert the the given type reference has the given identifier.
*
* @param actualReference - the actual type reference.
* @param expectedIdentifier - the expected identifier.
* @see JvmTypeReference#getIdentifier()
*/
public static void assertTypeReferenceIdentifier(JvmTypeReference actualReference, String expectedIdentifier) {
if (actualReference == null) {
assertEquals("void", expectedIdentifier);
return;
}
assertEquals("Unexpected type reference", expectedIdentifier, actualReference.getIdentifier());
}
/** Assert that the given actual formal parameters have the expected names.
*
* The order of the parameters and the expected names is significant.
*
* @param actualFormalParameters - the list of the formal parameters.
* @param expectedParameterNames - the expected names for the formal parameters.
*/
public static void assertParameterNames(Iterable<? extends XtendParameter> actualFormalParameters, String... expectedParameterNames) {
int i = 0;
for (XtendParameter parameter : actualFormalParameters) {
assertEquals("Unexpected parameter: " + parameter + ". Expected: " + expectedParameterNames[i],
parameter.getName(), expectedParameterNames[i]);
++i;
}
if (i < expectedParameterNames.length) {
fail("Not enough identifiers. Expected: " + Arrays.toString(expectedParameterNames)
+ "Actual: " + Iterables.toString(actualFormalParameters));
}
}
/** Assert that the given actual formal parameters have the expected types.
*
* The order of the parameters and the expected types is significant.
*
* @param actualFormalParameters - the list of the formal parameters.
* @param expectedParameterTypes - the expected types for the formal parameters.
*/
public static void assertParameterTypes(Iterable<? extends XtendParameter> actualFormalParameters, String... expectedParameterTypes) {
int i = 0;
for (XtendParameter parameter : actualFormalParameters) {
assertTypeReferenceIdentifier(
parameter.getParameterType(), expectedParameterTypes[i]);
++i;
}
if (i < expectedParameterTypes.length) {
fail("Not enough identifiers. Expected: " + Arrays.toString(expectedParameterTypes)
+ "Actual: " + Iterables.toString(actualFormalParameters));
}
}
/** Assert that the given actual formal parameters have the expected default values.
*
* The order of the parameters and the expected types is significant.
*
* The parameter <code>expectedDefaultValues</code> is a sequence of pairs, where
* the first element is the type of the default value and the second element is
* the representation of the default value.
* If the first element of the pair is null (meaning no default value), then
* the second element must be missed.
*
* @param actualFormalParameters - the list of the formal parameters.
* @param expectedDefaultValues - the expected default values.
*/
public static void assertParameterDefaultValues(Iterable<? extends XtendParameter> actualFormalParameters, Object... expectedDefaultValues) {
int i = 0;
for (XtendParameter parameter : actualFormalParameters) {
if (expectedDefaultValues[i] == null) {
if (parameter instanceof SarlFormalParameter) {
assertNull("No default value expected", ((SarlFormalParameter) parameter).getDefaultValue());
}
} else {
assertTrue(parameter instanceof SarlFormalParameter);
assertTrue("The #" + i + " in expectedDefaultValues is not a Class", expectedDefaultValues[i] instanceof Class);
Class type = (Class) expectedDefaultValues[i];
assertTrue("Unexpected type for the default value.", type.isInstance(((SarlFormalParameter) parameter).getDefaultValue()));
if (XNumberLiteral.class.isAssignableFrom(type)) {
++i;
assertEquals(expectedDefaultValues[i], ((XNumberLiteral) ((SarlFormalParameter) parameter).getDefaultValue()).getValue());
} else if (XStringLiteral.class.isAssignableFrom(type)) {
++i;
assertEquals(expectedDefaultValues[i], ((XStringLiteral) ((SarlFormalParameter) parameter).getDefaultValue()).getValue());
} else if (XNullLiteral.class.isAssignableFrom(type)) {
//
} else {
throw new RuntimeException("Unsupported type of literal for this assertion function");
}
}
++i;
}
if (i < expectedDefaultValues.length) {
fail("Not enough default values. Expected: " + Arrays.toString(expectedDefaultValues)
+ "Actual: " + Iterables.toString(actualFormalParameters));
}
}
/** Assert that the last parameter in the given actual formal parameters is variadic.
*
* @param actualFormalParameters
*/
public static void assertParameterVarArg(Iterable<? extends XtendParameter> actualFormalParameters) {
Iterator<? extends XtendParameter> iterator = actualFormalParameters.iterator();
XtendParameter lastParam = null;
while (iterator.hasNext()) {
lastParam = iterator.next();
}
if (lastParam == null || !lastParam.isVarArg()) {
fail("The last parameter is expected to be a variadic parameter.");
}
}
/** Assert that the last parameter in the given actual formal parameters is not variadic.
*
* @param actualFormalParameters
*/
public static void assertNoParameterVarArg(Iterable<? extends XtendParameter> actualFormalParameters) {
Iterator<? extends XtendParameter> iterator = actualFormalParameters.iterator();
XtendParameter lastParam = null;
while (iterator.hasNext()) {
lastParam = iterator.next();
}
if (lastParam != null && lastParam.isVarArg()) {
fail("The last parameter is expected to be not a variadic parameter.");
}
}
/** Assert the actual XExpression is of the given type and initialized with the given literal.
*
* @param actualExpression - the expression to test.
* @param expectedType - the expected type of expression.
* @param expectedValue - the expected value.
*/
public static void assertXExpression(XExpression actualExpression, Class<? extends XExpression> expectedType, String expectedValue) {
assertTrue("Expecting type of expression: " + expectedType.getName(),
expectedType.isInstance(actualExpression));
if (XNumberLiteral.class.isAssignableFrom(expectedType)) {
assertEquals("Invalid value.", expectedValue, ((XNumberLiteral) actualExpression).getValue());
}
else if (XStringLiteral.class.isAssignableFrom(expectedType)) {
assertEquals("Invalid value.", expectedValue, ((XStringLiteral) actualExpression).getValue());
}
else if (XNullLiteral.class.isAssignableFrom(expectedType)) {
//
}
}
/** Assert the actual object is a not-null instance of the given type.
*
* @param actualExpression - the expected type.
* @param expectedType - the instance.
*/
public static void assertInstanceOf(Class<?> expected, Object actual) {
assertInstanceOf(null, expected, actual);
}
/** Assert the actual object is a not-null instance of the given type.
*
* @param message - the error message.
* @param actualExpression - the expected type.
* @param expectedType - the instance.
*/
public static void assertInstanceOf(String message, Class<?> expected, Object actual) {
String m = message;
if (m == null) {
m = "Unexpected object type.";
}
if (actual == null) {
fail(m);
} else if (!expected.isInstance(actual)) {
throw new ComparisonFailure(
m,
expected.getName(),
actual.getClass().getName());
}
}
/** Create an instance of agent
*/
protected SarlAgent agent(String string) throws Exception {
List<XtendTypeDeclaration> decls = file(string).getXtendTypes();
return (SarlAgent) decls.get(decls.size() - 1);
}
/** Create an instance of agent
*/
protected SarlAgent agent(String string, boolean validate) throws Exception {
List<XtendTypeDeclaration> decls = file(string, validate).getXtendTypes();
return (SarlAgent) decls.get(decls.size() - 1);
}
/** Create an instance of capacity.
*/
protected SarlCapacity capacity(String string) throws Exception {
List<XtendTypeDeclaration> decls = file(string).getXtendTypes();
return (SarlCapacity) decls.get(decls.size() - 1);
}
/** Create an instance of capacity.
*/
protected SarlCapacity capacity(String string, boolean validate) throws Exception {
List<XtendTypeDeclaration> decls = file(string, validate).getXtendTypes();
return (SarlCapacity) decls.get(decls.size() - 1);
}
/** Create an instance of event.
*/
protected SarlEvent event(String string) throws Exception {
List<XtendTypeDeclaration> decls = file(string).getXtendTypes();
return (SarlEvent) decls.get(decls.size() - 1);
}
/** Create an instance of event.
*/
protected SarlEvent event(String string, boolean validate) throws Exception {
List<XtendTypeDeclaration> decls = file(string, validate).getXtendTypes();
return (SarlEvent) decls.get(decls.size() - 1);
}
/** Create an instance of skill.
*/
protected SarlSkill skill(String string) throws Exception {
List<XtendTypeDeclaration> decls = file(string).getXtendTypes();
return (SarlSkill) decls.get(decls.size() - 1);
}
/** Create an instance of skill.
*/
protected SarlSkill skill(String string, boolean validate) throws Exception {
List<XtendTypeDeclaration> decls = file(string, validate).getXtendTypes();
return (SarlSkill) decls.get(decls.size() - 1);
}
/** Create an instance of behavior.
*/
protected SarlBehavior behavior(String string) throws Exception {
List<XtendTypeDeclaration> decls = file(string).getXtendTypes();
return (SarlBehavior) decls.get(decls.size() - 1);
}
/** Create an instance of behavior.
*/
protected SarlBehavior behavior(String string, boolean validate) throws Exception {
List<XtendTypeDeclaration> decls = file(string, validate).getXtendTypes();
return (SarlBehavior) decls.get(decls.size() - 1);
}
/** Create an instance of class.
*/
protected SarlClass clazz(String string) throws Exception {
List<XtendTypeDeclaration> decls = file(string).getXtendTypes();
return (SarlClass) decls.get(decls.size() - 1);
}
/** Create an instance of class.
*/
protected SarlClass clazz(String string, boolean validate) throws Exception {
List<XtendTypeDeclaration> decls = file(string, validate).getXtendTypes();
return (SarlClass) decls.get(decls.size() - 1);
}
/** Create a SARL script.
*/
protected SarlScript file(String string) throws Exception {
return file(string, false);
}
/** Create an instance of class.
*/
protected SarlScript file(String string, boolean validate) throws Exception {
SarlScript script = this.parser.parse(string);
if (validate) {
Resource resource = script.eResource();
ResourceSet resourceSet = resource.getResourceSet();
if (resourceSet instanceof XtextResourceSet) {
((XtextResourceSet) resourceSet).setClasspathURIContext(getClass());
}
assertEquals(resource.getErrors().toString(), 0, resource.getErrors().size());
Collection<Issue> issues = Collections2.filter(issues(resource), new Predicate<Issue>() {
@Override
public boolean apply(Issue input) {
return input.getSeverity() == Severity.ERROR;
}
});
assertTrue("Resource contained errors : " + issues.toString(), issues.isEmpty());
}
return script;
}
/** Validate the given file and reply the issues.
*/
protected List<Issue> issues(SarlScript file) {
return issues(file.eResource());
}
/** Validate the given resource and reply the issues.
*/
protected List<Issue> issues(Resource resource) {
return this.validationHelper.validate(resource);
}
/** Validate the given file and reply the validator.
*/
protected Validator validate(SarlScript file) {
return validate(file.eResource());
}
/** Validate the given resource and reply the validator.
*/
protected Validator validate(Resource resource) {
Validator validator = new XtextValidator(resource);
this.injector.injectMembers(validator);
return validator;
}
/** Create an instance of annotation type.
*/
protected SarlAnnotationType annotationType(String string) throws Exception {
List<XtendTypeDeclaration> decls = file(string).getXtendTypes();
return (SarlAnnotationType) decls.get(decls.size() - 1);
}
/** Create an instance of annotation type.
*/
protected SarlAnnotationType annotationType(String string, boolean validate) throws Exception {
List<XtendTypeDeclaration> decls = file(string, validate).getXtendTypes();
return (SarlAnnotationType) decls.get(decls.size() - 1);
}
/** Create an instance of interface.
*/
protected SarlInterface interfaze(String string) throws Exception {
List<XtendTypeDeclaration> decls = file(string).getXtendTypes();
return (SarlInterface) decls.get(decls.size() - 1);
}
/** Create an instance of interface.
*/
protected SarlInterface interfaze(String string, boolean validate) throws Exception {
List<XtendTypeDeclaration> decls = file(string, validate).getXtendTypes();
return (SarlInterface) decls.get(decls.size() - 1);
}
/** Create an instance of enumeration.
*/
protected SarlEnumeration enumeration(String string) throws Exception {
List<XtendTypeDeclaration> decls = file(string).getXtendTypes();
return (SarlEnumeration) decls.get(decls.size() - 1);
}
/** Create an instance of enumeration.
*/
protected SarlEnumeration enumeration(String string, boolean validate) throws Exception {
List<XtendTypeDeclaration> decls = file(string, validate).getXtendTypes();
return (SarlEnumeration) decls.get(decls.size() - 1);
}
/** Create an instance of function.
*/
protected SarlAction function(String string, String... prefix) throws Exception {
SarlClass clazz = clazz(
IterableExtensions.join(Arrays.asList(prefix), getLineSeparator())
+ getLineSeparator() + "class Foo { " + string + "}");
return (SarlAction) clazz.getMembers().get(0);
}
/** Create an instance of function.
*/
protected SarlAction function(String string, boolean validate, String... prefix) throws Exception {
SarlClass clazz = clazz(
IterableExtensions.join(Arrays.asList(prefix), getLineSeparator())
+ getLineSeparator() + "class Foo { " + string + "}");
return (SarlAction) clazz.getMembers().get(0);
}
/** Create an instance of JVM function.
*/
protected JvmOperation jvmOperation(String string, String... prefix) throws Exception {
SarlAction action = function(string, prefix);
return (JvmOperation) this.associations.getPrimaryJvmElement(action);
}
/** Create an instance of JVM function.
*/
protected JvmOperation jvmOperation(String string, boolean validate, String... prefix) throws Exception {
SarlAction action = function(string, validate, prefix);
return (JvmOperation) this.associations.getPrimaryJvmElement(action);
}
/** Create an instance of function signature.
*/
protected SarlAction functionSignature(String string, String... prefix) throws Exception {
SarlInterface interfaze = interfaze(
IterableExtensions.join(Arrays.asList(prefix), getLineSeparator())
+ getLineSeparator() + "interface Foo { " + string + "}");
return (SarlAction) interfaze.getMembers().get(0);
}
/** Create an instance of function signature.
*/
protected SarlAction functionSignature(String string, boolean validate, String... prefix) throws Exception {
SarlInterface interfaze = interfaze(
IterableExtensions.join(Arrays.asList(prefix), getLineSeparator())
+ getLineSeparator() + "interface Foo { " + string + "}", validate);
return (SarlAction) interfaze.getMembers().get(0);
}
/** Create an instance of JVM function.
*/
protected JvmOperation jvmOperationSignature(String string, String... prefix) throws Exception {
SarlAction action = functionSignature(string, prefix);
return (JvmOperation) this.associations.getPrimaryJvmElement(action);
}
/** Create an instance of JVM function.
*/
protected JvmOperation jvmOperationSignature(String string, boolean validate, String... prefix) throws Exception {
SarlAction action = functionSignature(string, validate, prefix);
return (JvmOperation) this.associations.getPrimaryJvmElement(action);
}
/** Create an instance of constructor.
*/
protected SarlConstructor constructor(String string, String... prefix) throws Exception {
SarlClass clazz = clazz(
IterableExtensions.join(Arrays.asList(prefix), getLineSeparator())
+ getLineSeparator() + "class Foo { " + string + "}");
return (SarlConstructor) clazz.getMembers().get(0);
}
/** Create an instance of constructor.
*/
protected SarlConstructor constructor(String string, boolean validate, String... prefix) throws Exception {
SarlClass clazz = clazz(
IterableExtensions.join(Arrays.asList(prefix), getLineSeparator())
+ getLineSeparator() + "class Foo { " + string + "}", validate);
return (SarlConstructor) clazz.getMembers().get(0);
}
/** Create an instance of JVM constructor.
*/
protected JvmConstructor jvmConstructor(String string, String... prefix) throws Exception {
SarlConstructor constructor = constructor(string, prefix);
return (JvmConstructor) this.associations.getPrimaryJvmElement(constructor);
}
/** Create an instance of JVM constructor.
*/
protected JvmConstructor jvmConstructor(String string, boolean validate, String... prefix) throws Exception {
SarlConstructor constructor = constructor(string, validate, prefix);
return (JvmConstructor) this.associations.getPrimaryJvmElement(constructor);
}
/** Create an instance of field.
*/
protected SarlField field(String string, String... prefix) throws Exception {
SarlClass clazz = clazz(
IterableExtensions.join(Arrays.asList(prefix), getLineSeparator())
+ getLineSeparator() + "class Foo { " + string + "}");
return (SarlField) clazz.getMembers().get(0);
}
/** Create an instance of field.
*/
protected SarlField field(String string, boolean validate, String... prefix) throws Exception {
SarlClass clazz = clazz(
IterableExtensions.join(Arrays.asList(prefix), getLineSeparator())
+ getLineSeparator() + "class Foo { " + string + "}", validate);
return (SarlField) clazz.getMembers().get(0);
}
/** Create an instance of behavior unit.
*/
protected SarlBehaviorUnit behaviorUnit(String string, String... prefix) throws Exception {
SarlAgent agent = agent(
IterableExtensions.join(Arrays.asList(prefix), getLineSeparator())
+ getLineSeparator() + "agent Foo { " + string + "}");
return (SarlBehaviorUnit) agent.getMembers().get(0);
}
/** Create an instance of behavior unit.
*/
protected SarlBehaviorUnit behaviorUnit(String string, boolean validate, String... prefix) throws Exception {
SarlAgent agent = agent(
IterableExtensions.join(Arrays.asList(prefix), getLineSeparator())
+ getLineSeparator() + "agent Foo { " + string + "}", validate);
return (SarlBehaviorUnit) agent.getMembers().get(0);
}
/** Create a type reference with the SARL parser.
*/
protected JvmTypeReference getType(String typeName, String... prefix) throws Exception {
SarlAgent agent = agent(
IterableExtensions.join(Arrays.asList(prefix), getLineSeparator())
+ getLineSeparator() + "agent Foo { var fooAttr : " + typeName + " }");
return ((SarlField) agent.getMembers().get(0)).getType();
}
/** Merge two arrays.
*
* @param operand1 - the first array.
* @param operand2 - the second array.
* @return the merge.
*/
public static String[] merge(String[] operand1, String[] operand2) {
if (operand1 == null) {
if (operand2 == null) {
return new String[0];
}
return operand2;
}
if (operand2 == null) {
return operand1;
}
String[] tab = new String[operand1.length + operand2.length];
System.arraycopy(
operand1, 0,
tab, 0,
operand1.length);
System.arraycopy(
operand2, 0,
tab, operand1.length,
operand2.length);
return tab;
}
/** Replies the stack trace of the caller of this function.
*
* @return the stack trace.
*/
public static StackTraceElement[] getStackTrace() {
try {
throw new Exception();
} catch (Throwable e) {
List<StackTraceElement> types = new ArrayList<>();
StackTraceElement[] elements = e.getStackTrace();
for (int i = 1; i < elements.length; ++i) {
types.add(elements[i]);
}
StackTraceElement[] array = new StackTraceElement[types.size()];
types.toArray(array);
return array;
}
}
protected static void assertOsgiVersionEquals(Version expected, Version actual) {
if (Objects.equal(expected, actual)) {
return;
}
if (expected == null) {
fail("Version not null");
}
if (actual == null) {
fail("Unexpected null value");
}
if (expected.getMajor() == actual.getMajor()
&& expected.getMinor() == actual.getMinor()
&& expected.getMicro() == actual.getMicro()) {
if (!Strings.isNullOrEmpty(expected.getQualifier())) {
final String expectedQualifier = expected.getQualifier();
if ("qualifier".equals(expectedQualifier)) {
if (!Strings.isNullOrEmpty(actual.getQualifier())) {
return;
}
}
if (Objects.equal(expected, actual.getQualifier())) {
return;
}
} else {
return;
}
}
throw new ComparisonFailure("Not same versions", expected.toString(), actual.toString());
}
/** Mockito matcher that matches {@code null} or an instance of the given type.
*
* @param type the expected type.
* @return the default value for the given type.
*/
public static <T> T anyInstanceOrNull(Class<T> type) {
List<ArgumentMatcher> matchers = Arrays.asList(
Null.NULL,
new InstanceOf.VarArgAware(type));
ArgumentMatcher<T> or = new Or(matchers);
return ArgumentMatchers.argThat(or);
}
/** Validation helper on a specific resource.
*
* @author $Author: sgalland$
* @version $FullVersion$
* @mavengroupid $GroupId$
* @mavenartifactid $ArtifactId$
*/
public interface Validator {
List<Issue> getIssues();
Validator assertNoIssues();
Validator assertNoErrors();
Validator assertNoError(String issuecode);
Validator assertNoErrors(EClass objectType, String code, String... messageParts);
Validator assertNoErrors(String code);
Validator assertNoIssues(EClass objectType);
Validator assertNoIssue(EClass objectType, String issuecode);
Validator assertError(EClass objectType, String code, String... messageParts);
Validator assertIssue(EClass objectType, String code, Severity severity, String... messageParts);
Validator assertNoIssues(EClass objectType, String code, Severity severity, String... messageParts);
Validator assertWarning(EClass objectType, String code, String... messageParts);
Validator assertNoWarnings(EClass objectType, String code, String... messageParts);
}
/** Wrapper for the validation helper on a specific resource.
*
* @author $Author: sgalland$
* @version $FullVersion$
* @mavengroupid $GroupId$
* @mavenartifactid $ArtifactId$
*/
private class XtextValidator implements Validator {
private final Resource resource;
/**
* @param resource - the resource to validate.
*/
private XtextValidator(Resource resource) {
this.resource = resource;
}
public List<Issue> getIssues() {
return AbstractSarlTest.this.validationHelper.validate(this.resource);
}
public Validator assertNoIssues() {
AbstractSarlTest.this.validationHelper.assertNoIssues(this.resource);
return this;
}
public Validator assertNoErrors() {
AbstractSarlTest.this.validationHelper.assertNoErrors(this.resource);
return this;
}
public Validator assertNoError(String issuecode) {
AbstractSarlTest.this.validationHelper.assertNoError(this.resource, issuecode);
return this;
}
public Validator assertNoErrors(EClass objectType, String code, String... messageParts) {
AbstractSarlTest.this.validationHelper.assertNoErrors(this.resource, objectType, code, messageParts);
return this;
}
public Validator assertNoErrors(String code) {
AbstractSarlTest.this.validationHelper.assertNoErrors(this.resource, code);
return this;
}
public Validator assertNoIssues(EClass objectType) {
AbstractSarlTest.this.validationHelper.assertNoIssues(this.resource, objectType);
return this;
}
public Validator assertNoIssue(EClass objectType, String issuecode) {
AbstractSarlTest.this.validationHelper.assertNoIssue(this.resource, objectType, issuecode);
return this;
}
public Validator assertError(EClass objectType, String code, String... messageParts) {
AbstractSarlTest.this.validationHelper.assertError(this.resource, objectType, code, messageParts);
return this;
}
public Validator assertIssue(EClass objectType, String code, Severity severity, String... messageParts) {
AbstractSarlTest.this.validationHelper.assertIssue(this.resource, objectType, code, severity, messageParts);
return this;
}
public Validator assertNoIssues(EClass objectType, String code, Severity severity, String... messageParts) {
AbstractSarlTest.this.validationHelper.assertNoIssues(this.resource, objectType, code, severity, messageParts);
return this;
}
public Validator assertWarning(EClass objectType, String code, String... messageParts) {
AbstractSarlTest.this.validationHelper.assertWarning(this.resource, objectType, code, messageParts);
return this;
}
public Validator assertNoWarnings(EClass objectType, String code, String... messageParts) {
AbstractSarlTest.this.validationHelper.assertNoWarnings(this.resource, objectType, code, messageParts);
return this;
}
}
/**
* Extended utility class for reflection.
*
* @author $Author: sgalland$
* @version $FullVersion$
* @mavengroupid $GroupId$
* @mavenartifactid $ArtifactId$
*/
public static class ReflectExtensions {
/**
* Retrieves the value of the given accessible static field of the given type.
*
* @param receiverType the type of the container of the field, not <code>null</code>
* @param fieldName the field's name, not <code>null</code>
* @return the value of the field
*
* @throws NoSuchFieldException see {@link Class#getField(String)}
* @throws SecurityException see {@link Class#getField(String)}
* @throws IllegalAccessException see {@link Field#get(Object)}
* @throws IllegalArgumentException see {@link Field#get(Object)}
*/
public <T> T getStatic(Class<?> receiverType, String fieldName) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
Field f = getDeclaredField(receiverType, fieldName);
if (!f.isAccessible()) {
f.setAccessible(true);
}
return (T) f.get(null);
}
/**
* Set the value of the given accessible static field of the given type.
*
* @param receiverType the type of the container of the field, not <code>null</code>
* @param fieldName the field's name, not <code>null</code>
* @return the value of the field
*
* @throws NoSuchFieldException see {@link Class#getField(String)}
* @throws SecurityException see {@link Class#getField(String)}
* @throws IllegalAccessException see {@link Field#get(Object)}
* @throws IllegalArgumentException see {@link Field#get(Object)}
*/
public <T> void setStatic(Class<?> receiverType, String fieldName, Object value) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
Field f = getDeclaredField(receiverType, fieldName);
if (!f.isAccessible()) {
f.setAccessible(true);
}
f.set(null, value);
}
/**
* Set the value of the given accessible field of the given instance.
*
* @param instance the container of the field, not <code>null</code>
* @param fieldName the field's name, not <code>null</code>
* @return the value of the field
*/
public <T> void set(Object instance, String fieldName, Object value) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
Class<?> type = instance.getClass();
while (type != null) {
try {
Field f = getDeclaredField(type, fieldName);
if (!f.isAccessible()) {
f.setAccessible(true);
}
f.set(instance, value);
return;
} catch (NoSuchFieldException exception) {
//
}
type = type.getSuperclass();
}
throw new NoSuchFieldException(fieldName);
}
/**
* Replies the value of the given accessible field of the given instance.
*
* @param instance the container of the field, not <code>null</code>
* @param fieldName the field's name, not <code>null</code>
* @return the value of the field
*/
public <T> T get(Object instance, String fieldName) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
Class<?> type = instance.getClass();
while (type != null) {
try {
Field f = getDeclaredField(type, fieldName);
if (!f.isAccessible()) {
f.setAccessible(true);
}
return (T) f.get(instance);
} catch (NoSuchFieldException exception) {
//
}
type = type.getSuperclass();
}
throw new NoSuchFieldException(fieldName);
}
/**
* Invokes the first accessible constructor defined on the receiver's class with
* a parameter list compatible to the given arguments.
*
* @param <T> the type of the object to create.
* @param type type of the object to create.
* @param args the arguments for the method invocation
* @return the result of the constructor invocation.
* @throws InvocationTargetException
* @throws IllegalArgumentException
* @throws IllegalAccessException
* @throws InstantiationException
* @throws SecurityException
* @throws NoSuchMethodException
*/
public <T> T newInstance(Class<T> type, Object... args) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
final Object[] arguments = args == null ? new Object[]{null} : args;
Constructor<?> compatible = null;
for (Constructor<?> candidate : type.getDeclaredConstructors()) {
if (candidate != null && isCompatible(candidate, arguments)) {
if (compatible != null) {
throw new IllegalStateException(
"Ambiguous constructor to invoke. Both " //$NON-NLS-1$
+ compatible + " and " + candidate + " would be compatible choices."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-2
}
compatible = candidate;
}
}
if (compatible != null) {
if (!compatible.isAccessible()) {
compatible.setAccessible(true);
}
return type.cast(compatible.newInstance(arguments));
}
// not found provoke constructor not found exception
Class<?>[] paramTypes = new Class<?>[arguments.length];
for (int i = 0; i< arguments.length ; i++) {
paramTypes[i] = arguments[i] == null ? Object.class : arguments[i].getClass();
}
Constructor<T> cons = type.getConstructor(paramTypes);
return cons.newInstance(args);
}
protected static boolean isCompatible(Constructor<?> candidate, Object... args) {
if (candidate.getParameterTypes().length != args.length)
return false;
for (int i = 0; i< candidate.getParameterTypes().length; i++) {
Object param = args[i];
Class<?> class1 = candidate.getParameterTypes()[i];
if (class1.isPrimitive()) {
class1 = wrapperTypeFor(class1);
}
if (param != null && !class1.isInstance(param))
return false;
}
return true;
}
protected static Class<?> wrapperTypeFor(Class<?> primitive) {
assert primitive != null;
if (primitive == Boolean.TYPE) return Boolean.class;
if (primitive == Byte.TYPE) return Byte.class;
if (primitive == Character.TYPE) return Character.class;
if (primitive == Short.TYPE) return Short.class;
if (primitive == Integer.TYPE) return Integer.class;
if (primitive == Long.TYPE) return Long.class;
if (primitive == Float.TYPE) return Float.class;
if (primitive == Double.TYPE) return Double.class;
if (primitive == Void.TYPE) return Void.class;
throw new IllegalArgumentException(primitive+ " is not a primitive"); //$NON-NLS-1$
}
protected Field getDeclaredField(Class<?> clazz, String name) throws NoSuchFieldException {
NoSuchFieldException initialException = null;
do {
try {
Field f = clazz.getDeclaredField(name);
return f;
} catch(NoSuchFieldException noSuchField) {
if (initialException == null) {
initialException = noSuchField;
}
}
} while((clazz = clazz.getSuperclass()) != null);
throw initialException;
}
/**
* Invokes the first accessible constructor defined on the receiver's class with
* a parameter list compatible to the given arguments.
*
* @param <T> the type of the object to create.
* @param type type of the object to create.
* @param args the arguments for the method invocation
* @return the result of the constructor invocation.
* @throws InvocationTargetException
* @throws IllegalArgumentException
* @throws IllegalAccessException
* @throws InstantiationException
* @throws SecurityException
* @throws NoSuchMethodException
* @throws ClassNotFoundException
*/
public <T> T newInstance(String type, Object... args)
throws InstantiationException, IllegalAccessException, IllegalArgumentException,
InvocationTargetException, NoSuchMethodException, SecurityException, ClassNotFoundException {
final Class<?> t = forName(type);
return (T) newInstance(t, args);
}
/**
* Find the given type.
*
* @param name the name of the type.
* @return the class.
* @throws ClassNotFoundException
*/
public Class<?> forName(String name) throws ClassNotFoundException {
try {
return Class.forName(name);
} catch (Exception exception) {
//
}
BundleContext context = TestPluginActivator.context;
if (context != null) {
for (Bundle b : context.getBundles()) {
try {
return b.loadClass(name);
} catch (ClassNotFoundException e) {
// No problem, this bundle doesn't have the class
}
}
}
throw new ClassNotFoundException(name);
}
/**
* Invokes the first accessible method defined on the receiver'c class with the given name and
* a parameter list compatible to the given arguments.
*
* @param receiver the method call receiver, not <code>null</code>
* @param methodName the method name, not <code>null</code>
* @return the result of the method invocation. <code>null</code> if the method was of type void.
*/
public Object invoke(Object receiver, String methodName) throws SecurityException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
assert receiver != null;
assert methodName != null;
Class<? extends Object> clazz = receiver.getClass();
Method compatible = null;
do {
for (Method candidate : clazz.getDeclaredMethods()) {
if (candidate != null && !candidate.isBridge() && Objects.equal(methodName, candidate.getName())
&& candidate.getParameterCount() == 0) {
if (compatible != null)
throw new IllegalStateException("Ambiguous methods to invoke. Both "+compatible+" and "+candidate+" would be compatible choices.");
compatible = candidate;
}
}
} while(compatible == null && (clazz = clazz.getSuperclass()) != null);
if (compatible != null) {
if (!compatible.isAccessible())
compatible.setAccessible(true);
return compatible.invoke(receiver);
}
// not found provoke method not found exception
Method method = receiver.getClass().getMethod(methodName);
return method.invoke(receiver);
}
/**
* Invokes the first accessible method defined on the receiver'c class with the given name and
* a parameter list compatible to the given arguments.
*
* @param receiver the method call receiver, not <code>null</code>
* @param methodName the method name, not <code>null</code>
* @return the result of the method invocation. <code>null</code> if the method was of type void.
*/
public Object invoke(Object receiver, String methodName, Object... args) throws Exception, IllegalArgumentException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
assert receiver != null;
assert methodName != null;
if (args == null) {
args = new Object[] {null};
}
Class<? extends Object> clazz = receiver.getClass();
Method compatible = null;
do {
for (Method candidate : clazz.getDeclaredMethods()) {
if (candidate != null && !candidate.isBridge() && Objects.equal(methodName, candidate.getName())
&& isValidArgs(candidate.isVarArgs(), args, candidate.getParameterTypes())) {
if (compatible != null)
throw new IllegalStateException("Ambiguous methods to invoke. Both "+compatible+" and "+candidate+" would be compatible choices.");
compatible = candidate;
}
}
} while(compatible == null && (clazz = clazz.getSuperclass()) != null);
if (compatible != null) {
if (!compatible.isAccessible())
compatible.setAccessible(true);
if (compatible.isVarArgs()) {
Object[] newArgs = new Object[compatible.getParameterCount()];
for (int i = 0; i < compatible.getParameterCount() - 1; ++i) {
newArgs[i] = args[i];
}
Class<?> componentType = compatible.getParameterTypes()[compatible.getParameterCount() - 1].getComponentType();
int varArgsLength = args.length - compatible.getParameterCount() + 1;
Object varArgs = Array.newInstance(componentType, varArgsLength);
for (int i = 0; i < varArgsLength; ++i) {
Array.set(varArgs, i, args[i + compatible.getParameterCount() - 1]);
}
newArgs[compatible.getParameterCount() - 1] = varArgs;
return compatible.invoke(compatible.getDeclaringClass().cast(receiver), (Object[]) newArgs);
}
return compatible.invoke(compatible.getDeclaringClass().cast(receiver), (Object[]) args);
}
// not found provoke method not found exception
Method method = receiver.getClass().getMethod(methodName);
return method.invoke(receiver);
}
private static boolean isValidArgs(boolean varargs, Object[] args, Class<?>[] params) {
for (int i = 0; i < args.length; ++i) {
if (i >= params.length) {
return false;
}
if (args[i] == null) {
if (params[i].isPrimitive()) {
return false;
}
} else if ((!(params[i].isInstance(args[i]))) && varargs && i == params.length - 1) {
Class<?> componentType = params[i].getComponentType();
Class<?>[] newParams = new Class[args.length - params.length + 1];
for (int j = 0; j < newParams.length; ++j) {
newParams[j] = componentType;
}
Object[] newArgs = new Object[newParams.length];
for (int j = 0; j < newArgs.length; ++j, ++i) {
newArgs[j] = args[i];
}
return isValidArgs(false, newArgs, newParams);
} else if (!(params[i].isInstance(args[i]))) {
if (Primitives.isPrimitiveOrWrapper(params[i])) {
if (!Objects.equal(
Primitives.primitiveTypeOf(params[i]),
Primitives.primitiveTypeOf(args[i].getClass()))) {
return false;
}
} else {
return false;
}
}
}
return true;
}
}
}